#include "audiodataprocess.h"
#include "sndfile.h"
#include "samplerate.h"
#include <QDebug>
#include <QFile>
#include <QTimer>
#include <math.h>
#include "fftw3.h"

const float conv_mul = 0.15;

void AudioDataProcess::arm_conv_f32(
    const float * pSrcA,
    uint32_t srcALen,
    const float * pSrcB,
    uint32_t srcBLen,
    float * pDst)
{
    const float *pIn1;                               /* InputA pointer */
    const float *pIn2;                               /* InputB pointer */
    float *pOut = pDst;                        /* Output pointer */
    const float *px;                                 /* Intermediate inputA pointer */
    const float *py;                                 /* Intermediate inputB pointer */
    const float *pSrc1, *pSrc2;                      /* Intermediate pointers */
    float sum;                                 /* Accumulators */
    uint32_t blockSize1, blockSize2, blockSize3;   /* Loop counters */
    uint32_t j, k, count, blkCnt;                  /* Loop counters */

    float acc0, acc1, acc2, acc3, c0;              /* Accumulators */
    float x0, x1, x2, x3;                  /* Temporary variables to hold state and coefficient values */

    /* The algorithm implementation is based on the lengths of the inputs. */
    /* srcB is always made to slide across srcA. */
    /* So srcBLen is always considered as shorter or equal to srcALen */
    if (srcALen >= srcBLen)
    {
        /* Initialization of inputA pointer */
        pIn1 = pSrcA;

        /* Initialization of inputB pointer */
        pIn2 = pSrcB;
    }
    else
    {
        /* Initialization of inputA pointer */
        pIn1 = pSrcB;

        /* Initialization of inputB pointer */
        pIn2 = pSrcA;

        /* srcBLen is always considered as shorter or equal to srcALen */
        j = srcBLen;
        srcBLen = srcALen;
        srcALen = j;
    }

    /* conv(x,y) at n = x[n] * y[0] + x[n-1] * y[1] + x[n-2] * y[2] + ...+ x[n-N+1] * y[N -1] */
    /* The function is internally
   * divided into three stages according to the number of multiplications that has to be
   * taken place between inputA samples and inputB samples. In the first stage of the
   * algorithm, the multiplications increase by one for every iteration.
   * In the second stage of the algorithm, srcBLen number of multiplications are done.
   * In the third stage of the algorithm, the multiplications decrease by one
   * for every iteration. */

    /* The algorithm is implemented in three stages.
     The loop counters of each stage is initiated here. */
    blockSize1 = srcBLen - 1U;
    blockSize2 = srcALen - (srcBLen - 1U);
    blockSize3 = blockSize1;

    /* --------------------------
   * Initializations of stage1
   * -------------------------*/

    /* sum = x[0] * y[0]
   * sum = x[0] * y[1] + x[1] * y[0]
   * ....
   * sum = x[0] * y[srcBlen - 1] + x[1] * y[srcBlen - 2] +...+ x[srcBLen - 1] * y[0]
   */

    /* In this stage the MAC operations are increased by 1 for every iteration.
     The count variable holds the number of MAC operations performed */
    count = 1U;

    /* Working pointer of inputA */
    px = pIn1;

    /* Working pointer of inputB */
    py = pIn2;

    /* The first stage starts here */
    while (blockSize1 > 0U)
    {
        /* Accumulator is made zero for every iteration */
        sum = 0.0f;

        k = count >> 2U;

        while (k > 0U)
        {
            /* x[0] * y[srcBLen - 1] */
            sum += *px++ * *py--;

            /* x[1] * y[srcBLen - 2] */
            sum += *px++ * *py--;

            /* x[2] * y[srcBLen - 3] */
            sum += *px++ * *py--;

            /* x[3] * y[srcBLen - 4] */
            sum += *px++ * *py--;

            /* Decrement loop counter */
            k--;
        }

        /* Loop unrolling: Compute remaining outputs */
        k = count % 0x4U;

        while (k > 0U)
        {
            /* Perform the multiply-accumulate */
            sum += *px++ * *py--;

            /* Decrement loop counter */
            k--;
        }

        /* Store the result in the accumulator in the destination buffer. */
        *pOut++ = sum * conv_mul;
        deal_sample_count ++;

        /* Update the inputA and inputB pointers for next MAC calculation */
        py = pIn2 + count;
        px = pIn1;

        /* Increment MAC count */
        count++;

        /* Decrement loop counter */
        blockSize1--;
    }

    /* --------------------------
   * Initializations of stage2
   * ------------------------*/

    /* sum = x[0] * y[srcBLen-1] + x[1] * y[srcBLen-2] +...+ x[srcBLen-1] * y[0]
   * sum = x[1] * y[srcBLen-1] + x[2] * y[srcBLen-2] +...+ x[srcBLen]   * y[0]
   * ....
   * sum = x[srcALen-srcBLen-2] * y[srcBLen-1] + x[srcALen] * y[srcBLen-2] +...+ x[srcALen-1] * y[0]
   */

    /* Working pointer of inputA */
    px = pIn1;

    /* Working pointer of inputB */
    pSrc2 = pIn2 + (srcBLen - 1U);
    py = pSrc2;

    /* count is index by which the pointer pIn1 to be incremented */
    count = 0U;

    /* -------------------
   * Stage2 process
   * ------------------*/

    /* Stage2 depends on srcBLen as in this stage srcBLen number of MACS are performed.
   * So, to loop unroll over blockSize2,
   * srcBLen should be greater than or equal to 4 */
    if (srcBLen >= 4U)
    {
        /* Loop unrolling: Compute 4 outputs at a time */
        blkCnt = blockSize2 >> 2U;

        while (blkCnt > 0U)
        {
            /* Set all accumulators to zero */
            acc0 = 0.0f;
            acc1 = 0.0f;
            acc2 = 0.0f;
            acc3 = 0.0f;

            /* Apply loop unrolling and compute 4 MACs simultaneously. */
            k = srcBLen >> 2U;

            /* read x[0], x[1], x[2] samples */
            x0 = *px++;
            x1 = *px++;
            x2 = *px++;

            /* First part of the processing with loop unrolling.  Compute 4 MACs at a time.
       ** a second loop below computes MACs for the remaining 1 to 3 samples. */
            do
            {
                /* Read y[srcBLen - 1] sample */
                c0 = *py--;
                /* Read x[3] sample */
                x3 = *(px);

                /* Perform the multiply-accumulate */
                /* acc0 +=  x[0] * y[srcBLen - 1] */
                acc0 += x0 * c0;
                /* acc1 +=  x[1] * y[srcBLen - 1] */
                acc1 += x1 * c0;
                /* acc2 +=  x[2] * y[srcBLen - 1] */
                acc2 += x2 * c0;
                /* acc3 +=  x[3] * y[srcBLen - 1] */
                acc3 += x3 * c0;

                /* Read y[srcBLen - 2] sample */
                c0 = *py--;
                /* Read x[4] sample */
                x0 = *(px + 1U);

                /* Perform the multiply-accumulate */
                /* acc0 +=  x[1] * y[srcBLen - 2] */
                acc0 += x1 * c0;
                /* acc1 +=  x[2] * y[srcBLen - 2] */
                acc1 += x2 * c0;
                /* acc2 +=  x[3] * y[srcBLen - 2] */
                acc2 += x3 * c0;
                /* acc3 +=  x[4] * y[srcBLen - 2] */
                acc3 += x0 * c0;

                /* Read y[srcBLen - 3] sample */
                c0 = *py--;
                /* Read x[5] sample */
                x1 = *(px + 2U);

                /* Perform the multiply-accumulate */
                /* acc0 +=  x[2] * y[srcBLen - 3] */
                acc0 += x2 * c0;
                /* acc1 +=  x[3] * y[srcBLen - 2] */
                acc1 += x3 * c0;
                /* acc2 +=  x[4] * y[srcBLen - 2] */
                acc2 += x0 * c0;
                /* acc3 +=  x[5] * y[srcBLen - 2] */
                acc3 += x1 * c0;

                /* Read y[srcBLen - 4] sample */
                c0 = *py--;
                /* Read x[6] sample */
                x2 = *(px + 3U);
                px += 4U;

                /* Perform the multiply-accumulate */
                /* acc0 +=  x[3] * y[srcBLen - 4] */
                acc0 += x3 * c0;
                /* acc1 +=  x[4] * y[srcBLen - 4] */
                acc1 += x0 * c0;
                /* acc2 +=  x[5] * y[srcBLen - 4] */
                acc2 += x1 * c0;
                /* acc3 +=  x[6] * y[srcBLen - 4] */
                acc3 += x2 * c0;

            } while (--k);

            /* If the srcBLen is not a multiple of 4, compute any remaining MACs here.
       ** No loop unrolling is used. */
            k = srcBLen % 0x4U;

            while (k > 0U)
            {
                /* Read y[srcBLen - 5] sample */
                c0 = *py--;
                /* Read x[7] sample */
                x3 = *px++;

                /* Perform the multiply-accumulate */
                /* acc0 +=  x[4] * y[srcBLen - 5] */
                acc0 += x0 * c0;
                /* acc1 +=  x[5] * y[srcBLen - 5] */
                acc1 += x1 * c0;
                /* acc2 +=  x[6] * y[srcBLen - 5] */
                acc2 += x2 * c0;
                /* acc3 +=  x[7] * y[srcBLen - 5] */
                acc3 += x3 * c0;

                /* Reuse the present samples for the next MAC */
                x0 = x1;
                x1 = x2;
                x2 = x3;

                /* Decrement the loop counter */
                k--;
            }
            /* Store the result in the accumulator in the destination buffer. */
            *pOut++ = acc0 * conv_mul;
            *pOut++ = acc1 * conv_mul;
            *pOut++ = acc2 * conv_mul;
            *pOut++ = acc3 * conv_mul;
            deal_sample_count += 4;

            /* Increment the pointer pIn1 index, count by 4 */
            count += 4U;

            /* Update the inputA and inputB pointers for next MAC calculation */
            px = pIn1 + count;
            py = pSrc2;

            /* Decrement the loop counter */
            blkCnt--;
        }

        /* If the blockSize2 is not a multiple of 4, compute any remaining output samples here.
     ** No loop unrolling is used. */
        blkCnt = blockSize2 % 0x4U;

        while (blkCnt > 0U)
        {
            /* Accumulator is made zero for every iteration */
            sum = 0.0f;

            /* Loop unrolling: Compute 4 outputs at a time */
            k = srcBLen >> 2U;

            while (k > 0U)
            {
                /* Perform the multiply-accumulate */
                sum += *px++ * *py--;
                sum += *px++ * *py--;
                sum += *px++ * *py--;
                sum += *px++ * *py--;

                /* Decrement loop counter */
                k--;
            }

            /* Loop unrolling: Compute remaining outputs */
            k = srcBLen % 0x4U;

            while (k > 0U)
            {
                /* Perform the multiply-accumulate */
                sum += *px++ * *py--;

                /* Decrement the loop counter */
                k--;
            }

            /* Store the result in the accumulator in the destination buffer. */
            *pOut++ = sum * conv_mul;
            deal_sample_count ++;

            /* Increment the MAC count */
            count++;

            /* Update the inputA and inputB pointers for next MAC calculation */
            px = pIn1 + count;
            py = pSrc2;

            /* Decrement the loop counter */
            blkCnt--;
        }
    }
    else
    {
        /* If the srcBLen is not a multiple of 4,
     * the blockSize2 loop cannot be unrolled by 4 */
        blkCnt = blockSize2;

        while (blkCnt > 0U)
        {
            /* Accumulator is made zero for every iteration */
            sum = 0.0f;

            /* srcBLen number of MACS should be performed */
            k = srcBLen;

            while (k > 0U)
            {
                /* Perform the multiply-accumulate */
                sum += *px++ * *py--;

                /* Decrement the loop counter */
                k--;
            }

            /* Store the result in the accumulator in the destination buffer. */
            *pOut++ = sum * conv_mul;
            deal_sample_count ++;

            /* Increment the MAC count */
            count++;

            /* Update the inputA and inputB pointers for next MAC calculation */
            px = pIn1 + count;
            py = pSrc2;

            /* Decrement the loop counter */
            blkCnt--;
        }
    }


    /* --------------------------
   * Initializations of stage3
   * -------------------------*/

    /* sum += x[srcALen-srcBLen+1] * y[srcBLen-1] + x[srcALen-srcBLen+2] * y[srcBLen-2] +...+ x[srcALen-1] * y[1]
   * sum += x[srcALen-srcBLen+2] * y[srcBLen-1] + x[srcALen-srcBLen+3] * y[srcBLen-2] +...+ x[srcALen-1] * y[2]
   * ....
   * sum +=  x[srcALen-2] * y[srcBLen-1] + x[srcALen-1] * y[srcBLen-2]
   * sum +=  x[srcALen-1] * y[srcBLen-1]
   */

    /* In this stage the MAC operations are decreased by 1 for every iteration.
     The blockSize3 variable holds the number of MAC operations performed */

    /* Working pointer of inputA */
    pSrc1 = pIn1 + (srcALen - (srcBLen - 1U));
    px = pSrc1;

    /* Working pointer of inputB */
    pSrc2 = pIn2 + (srcBLen - 1U);
    py = pSrc2;

    /* -------------------
   * Stage3 process
   * ------------------*/
    while (blockSize3 > 0U)
    {
        /* Accumulator is made zero for every iteration */
        sum = 0.0f;

        /* Loop unrolling: Compute 4 outputs at a time */
        k = blockSize3 >> 2U;

        while (k > 0U)
        {
            /* Perform the multiply-accumulate */
            /* sum += x[srcALen - srcBLen + 1] * y[srcBLen - 1] */
            sum += *px++ * *py--;

            /* sum += x[srcALen - srcBLen + 2] * y[srcBLen - 2] */
            sum += *px++ * *py--;

            /* sum += x[srcALen - srcBLen + 3] * y[srcBLen - 3] */
            sum += *px++ * *py--;

            /* sum += x[srcALen - srcBLen + 4] * y[srcBLen - 4] */
            sum += *px++ * *py--;

            /* Decrement loop counter */
            k--;
        }

        /* Loop unrolling: Compute remaining outputs */
        k = blockSize3 % 0x4U;
        while (k > 0U)
        {
            /* Perform the multiply-accumulate */
            /* sum +=  x[srcALen-1] * y[srcBLen-1] */
            sum += *px++ * *py--;

            /* Decrement loop counter */
            k--;
        }

        /* Store the result in the accumulator in the destination buffer. */
        *pOut++ = sum * conv_mul;
        deal_sample_count ++;

        /* Update the inputA and inputB pointers for next MAC calculation */
        px = ++pSrc1;
        py = pSrc2;

        /* Decrement the loop counter */
        blockSize3--;
    }
}


// 获取大于等于n的最小的2的幂次方
int next_power_of_two(int n) {
    int power = 1;
    while (power < n) {
        power *= 2;
    }
    return power;
}

// 定义卷积函数
void AudioDataProcess::convolution_fft(const float* signal_data, int signal_length, const float* kernel_data, int kernel_length, float* output) {
    // int padded_size = next_power_of_two(signal_length + kernel_length - 1); // 补零后的长度
    int padded_size = signal_length + kernel_length - 1;

    // 创建FFTW计划
    fftwf_complex* in1, * in2, * out;
    fftwf_plan plan_signal, plan_kernel, plan_backward;

    in1 = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * padded_size);
    in2 = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * padded_size);
    out = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * padded_size);
    ::memset(in1,0,sizeof(fftwf_complex) * padded_size);
    ::memset(in2,0,sizeof(fftwf_complex) * padded_size);

    plan_signal = fftwf_plan_dft_1d(padded_size, in1, in1, FFTW_FORWARD, FFTW_ESTIMATE);
    plan_kernel = fftwf_plan_dft_1d(padded_size, in2, in2, FFTW_FORWARD, FFTW_ESTIMATE);
    plan_backward = fftwf_plan_dft_1d(padded_size, out, out, FFTW_BACKWARD, FFTW_ESTIMATE);

    // 将输入复制到FFTW复数数组中
    for (int i = 0; i < signal_length; i++) {
        in1[i][0] = signal_data[i];
        // in1[i][1] = 0.0;  // 虚部设为0
    }

    for (int i = 0; i < kernel_length; i++) {
        in2[i][0] = kernel_data[i];
        // in2[i][1] = 0.0;  // 虚部设为0
    }


    // 执行傅里叶变换
    fftwf_execute(plan_signal);
    fftwf_execute(plan_kernel);

    // 执行频域上的乘积运算
    for (int i = 0; i < padded_size; i++) {
        double real1 = in1[i][0];
        double imag1 = in1[i][1];

        double real2 = in2[i][0];
        double imag2 = in2[i][1];

        // 复数乘法
        out[i][0] = real1 * real2 - imag1 * imag2;
        out[i][1] = real1 * imag2 + imag1 * real2;
    }

    // 执行逆傅里叶变换
    fftwf_execute(plan_backward);

    // 将结果写回输出数组
    double aa = padded_size * (5 + (kernel_length / 9600));
    for (int i = 0; i < padded_size; i++) {
        output[i] = (float)((double)out[i][0] / aa);  // 除以padded_size进行归一化
        // output[i] = output[i] * aa;
        if(output[i] > 1)
        {
            output[i] = 1;
        }
        else if(output[i] < -1)
        {
            output[i] = -1;
        }
    }

    // 清理内存和计划
    fftwf_destroy_plan(plan_signal);
    fftwf_destroy_plan(plan_kernel);
    fftwf_destroy_plan(plan_backward);
    fftwf_free(in1);
    fftwf_free(in2);
    fftwf_free(out);
}

void AudioDataProcess::compute_progress()
{
    int p = get_progress();
    qInfo() << p << "%";
    emit deal_progress(p);
}

AudioDataProcess::AudioDataProcess(QObject *parent)
    : QObject{parent}
{

    thread = new QThread;
    moveToThread(thread);
    thread->start(QThread::HighestPriority);
    // snd_file = nullptr;
    audio_data.clear();

    qInfo() << "libsndfile version:" << sf_version_string();
}

AudioDataProcess::~AudioDataProcess()
{
    // if(snd_file != nullptr)
    // {
    //     sf_close(snd_file);
    //     snd_file = nullptr;
    // }
    for (int i = 0; i < audio_data.size(); ++i)
    {
        delete[] audio_data[i];
    }
    for (int i = 0; i < ir_data.size(); ++i)
    {
        delete[] ir_data[i];
    }
}

void AudioDataProcess::convolution(const float *signal, int signal_length, const float *kernel, int kernel_length, float *result)
{
#if 0
    int k,s;
    float sd;
    float *pRes;
    for (s = 0; s < signal_length; s++)
    {
        sd = signal[s];
        pRes = result+s;
        for (k = 0; k < kernel_length; k++)
        {
            //result[offset++] += (kernel[k] * sd) * 0.15;
            *pRes++ += kernel[k] * sd;
        }
        deal_sample_count++;
    }
    pRes = result;
    k = signal_length + kernel_length - 1;
    s = 0;
    while(s < k)
    {
        *pRes = *pRes * 0.1;
        pRes++;
        s++;
    }
    // deal_sample_count = deal_sample_max;

#else
    convolution_fft(signal, signal_length, kernel, kernel_length, result);
    // arm_conv_f32(signal,signal_length,kernel,kernel_length,result);
#endif
}

AudioDataProcess::AUDIO_PROCESS_STATUS AudioDataProcess::open_audio_file(const QString &path,float **data_out,int *channels,int *sample_rate,int *frames)
{
    SF_INFO snd_info;
    SNDFILE *snd_file;

    if((data_out == nullptr) || (channels == nullptr) || (frames == nullptr))
    {
        return HANDLE_IS_NONE;
    }


    QByteArray ba = path.toUtf8();
    const char *path_data = (const char *)ba.data();
    qInfo() << "open file :" << path_data;
    snd_file = sf_open(path_data,SFM_READ,&snd_info);
    if(!snd_file)
    {
        qCritical() << "open file error";
        return OPEN_FILE_FAILED;
    }

    // for (int i = 0; i < audio_data.size(); ++i) {
    //     if(audio_data[i] != nullptr)
    //     {
    //         delete[] audio_data[i];
    //         audio_data[i] = nullptr;
    //     }
    // }
    // audio_data.clear();

    *channels = snd_info.channels;
    *sample_rate = snd_info.samplerate;
    *frames = snd_info.frames;
    qInfo() << "通道数:" << *channels;
    qInfo() << "采样率:" << *sample_rate;
    qInfo() << "样本数:" << *frames;
    *data_out = new float[snd_info.frames * snd_info.channels];
    sf_read_float(snd_file,*data_out,snd_info.frames * snd_info.channels);
    sf_close(snd_file);
    // SNDFILE *osnd;
    // SF_INFO oinfo;
    // oinfo.channels = 1;
    // oinfo.samplerate = sample_rate;
    // oinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
    // osnd = sf_open("test.wav",SFM_WRITE,&oinfo);
    // if(osnd)
    // {
    //     rd = sf_write_short(osnd,audio_data[0],frames);
    //     qInfo() << "wrd:" << rd;
    //     sf_close(osnd);
    // }

    return SUCCESS;
}

AudioDataProcess::AUDIO_PROCESS_STATUS AudioDataProcess::open_ir_file(const QString &path)
{
    SF_INFO snd_info;
    SNDFILE *snd_file;
    int ir_channels;
    int ir_sample_rate;
    int ir_frames;

    QByteArray ba = path.toUtf8();
    const char *path_data = (const char *)ba.data();

    qInfo() << "open ir file :" << path_data;

    snd_file = sf_open(path_data,SFM_READ,&snd_info);
    if(!snd_file)
    {
        qCritical() << "open file error";
        return OPEN_FILE_FAILED;
    }

    for (int i = 0; i < ir_data.size(); ++i) {
        if(ir_data[i] != nullptr)
        {
            delete[] ir_data[i];
            ir_data[i] = nullptr;
        }
    }
    ir_data.clear();

    ir_channels = snd_info.channels;
    ir_sample_rate = snd_info.samplerate;
    ir_frames = snd_info.frames;
    qInfo() << "通道数:" << ir_channels;
    qInfo() << "采样率:" << ir_sample_rate;
    qInfo() << "样本数:" << ir_frames;
    float *buff_all;
    float *buff_mono;
    buff_all = new float[ir_frames * ir_channels];
    sf_read_float(snd_file,buff_all,ir_frames * ir_channels);
    sf_close(snd_file);
    for(int i=0; i<ir_channels; i++)
    {
        buff_mono = new float[ir_frames];
        ir_data.append(buff_mono);
        for(int f=0; f<ir_frames; f++)
        {
            buff_mono[f] = buff_all[f * ir_channels + i];
        }
    }
    delete[] buff_all;

    return SUCCESS;
}

AudioDataProcess::AUDIO_PROCESS_STATUS AudioDataProcess::set_audio_file_path(const QString &path)
{
    if(QFile(path).exists())
    {
        audio_file_path = path;
        return SUCCESS;
    }
    audio_file_path = "";
    return FILE_NOT_EXISTS;
}

AudioDataProcess::AUDIO_PROCESS_STATUS AudioDataProcess::set_ir_file_path(const QString &path)
{
    if(QFile(path).exists())
    {
        ir_file_path = path;
        return SUCCESS;
    }
    ir_file_path = "";
    return FILE_NOT_EXISTS;
}

int AudioDataProcess::get_progress()
{
    double a = deal_sample_count;
    double b = deal_sample_max;
    int c = (a / b) * 100;

    return c;
}

void AudioDataProcess::create_file()
{
    int audio_channels=0;
    int audio_sample_rate=0;
    int audio_frames=0;
    int ir_channels;
    int ir_sample_rate;
    int ir_frames;

    float *ir_file_data_buff;
    float *audio_file_data_buff;
    float *new_sample_buff;
    AUDIO_PROCESS_STATUS res;

    deal_sample_max = 0x7FFFFFFF;
    deal_sample_count = 0;

    if(audio_file_path.isEmpty())
    {
        qDebug() << "没有加载音频文件";
        return ;
    }
    if(ir_file_path.isEmpty())
    {
        qDebug() << "没有加载IR文件";
        return ;
    }

    audio_file_data_buff = nullptr;
    qInfo() << "开始读取音频文件";
    res = open_audio_file(audio_file_path,&audio_file_data_buff,&audio_channels,&audio_sample_rate,&audio_frames);
    if((res != SUCCESS) || (audio_file_data_buff == nullptr))
    {
        qCritical() << "读取文件数据失败," << audio_file_path;
        if(audio_file_data_buff != nullptr)
        {
            delete[] audio_file_data_buff;
        }
        return ;
    }
    if(audio_channels == 0)
    {
        qCritical() << "通道错误," << audio_channels << ",file:" << audio_file_path;
        if(audio_file_data_buff != nullptr)
        {
            delete[] audio_file_data_buff;
        }
        return ;
    }
    if(audio_sample_rate == 0)
    {
        qCritical() << "采样率错误," << audio_sample_rate << ",file:" << audio_file_path;
        if(audio_file_data_buff != nullptr)
        {
            delete[] audio_file_data_buff;
        }
        return ;
    }
    if(audio_frames == 0)
    {
        qCritical() << "帧长度错误," << audio_frames << ",file:" << audio_file_path;
        if(audio_file_data_buff != nullptr)
        {
            delete[] audio_file_data_buff;
        }
        return ;
    }
    qInfo() << "开始读取IR文件";
    ir_file_data_buff = nullptr;
    res = open_audio_file(ir_file_path,&ir_file_data_buff,&ir_channels,&ir_sample_rate,&ir_frames);
    if((res != SUCCESS) || (ir_file_data_buff == nullptr))
    {
        qCritical() << "读取文件数据失败," << ir_file_path;
        if(ir_file_data_buff != nullptr)
        {
            delete[] ir_file_data_buff;
        }
        return ;
    }
    if(ir_channels == 0)
    {
        qCritical() << "通道错误," << ir_channels << ",file:" << ir_file_path;
        if(ir_file_data_buff != nullptr)
        {
            delete[] ir_file_data_buff;
        }
        return ;
    }
    if(ir_sample_rate == 0)
    {
        qCritical() << "采样率错误," << ir_sample_rate << ",file:" << ir_file_path;
        if(ir_file_data_buff != nullptr)
        {
            delete[] ir_file_data_buff;
        }
        return ;
    }
    if(ir_frames == 0)
    {
        qCritical() << "帧长度错误," << ir_frames << ",file:" << ir_file_path;
        if(ir_file_data_buff != nullptr)
        {
            delete[] ir_file_data_buff;
        }
        return ;
    }

    //检查采样率
    if(audio_sample_rate != ir_sample_rate)
    {
        qInfo() << "音频文件采样率为" << audio_sample_rate << ",IR文件采样率为" << ir_sample_rate;
        qInfo() << "开始音频文件转换采样率为" << ir_sample_rate;
        int error;
        SRC_STATE *src_stae = src_new(SRC_SINC_BEST_QUALITY,audio_channels,&error);
        if(src_stae == nullptr)
        {
            qCritical() << "src_new failed " << src_strerror(error);
            delete[] audio_file_data_buff;
            delete[] ir_file_data_buff;
            return ;
        }
        else
        {
            // double new_rate = (double)audio_sample_rate / (double)ir_sample_rate;
            double new_rate = (double)ir_sample_rate / (double)audio_sample_rate;
            int out_samples = (int)(new_rate * audio_frames);
            new_sample_buff = new float[out_samples * audio_channels + audio_channels];
            ::memset(new_sample_buff,0,(out_samples * audio_channels + audio_channels) * sizeof(float));
            qInfo() << "设置转换比率" << new_rate;
            int r = src_set_ratio(src_stae,new_rate);
            if(r)
            {
                qCritical() << "设置采样率出错 " << r << "," << src_strerror(r);
                delete[] new_sample_buff;
                delete[] audio_file_data_buff;
                src_delete(src_stae);
                return ;
            }
            else
            {
                SRC_DATA src_data;
                src_data.data_in = audio_file_data_buff;
                src_data.input_frames = audio_frames;
                src_data.data_out = new_sample_buff;
                src_data.output_frames = out_samples;
                src_data.src_ratio = new_rate;
                r = src_process(src_stae,&src_data);
                if(r)
                {
                    // qInfo() << "test ratre " << src_is_valid_ratio(new_rate);
                    qCritical() << "转换采样率出错 " << r << "," << src_strerror(r);
                    delete[] new_sample_buff;
                    delete[] audio_file_data_buff;
                    src_delete(src_stae);
                    return ;
                }
                else
                {
                    src_delete(src_stae);
                    delete[] audio_file_data_buff;
                    audio_file_data_buff = new_sample_buff;
                    qInfo() << "转换采样率完成";
                    audio_frames = out_samples;
                }
            }
        }
    }
    qInfo() << "分离音频文件声道";
    for (int i = 0; i < audio_data.size(); ++i) {
        if(audio_data[i] != nullptr)
        {
            delete[] audio_data[i];
            audio_data[i] = nullptr;
        }
    }
    for (int i = 0; i < ir_data.size(); ++i) {
        if(ir_data[i] != nullptr)
        {
            delete[] ir_data[i];
            ir_data[i] = nullptr;
        }
    }
    for (int i = 0; i < result_data.size(); ++i) {
        if(result_data[i] != nullptr)
        {
            delete[] result_data[i];
            result_data[i] = nullptr;
        }
    }
    audio_data.clear();
    ir_data.clear();
    result_data.clear();
    //分离声道,每个声道分开处理
    float *buff_mono;
    for(int i=0; i<audio_channels; i++)
    {
        buff_mono = new float[audio_frames];
        for(int f=0; f<audio_frames; f++)
        {
            buff_mono[f] = audio_file_data_buff[f * audio_channels + i];
        }
        audio_data.append(buff_mono);
    }
    delete[] audio_file_data_buff;

    for(int i=0; i<ir_channels; i++)
    {
        buff_mono = new float[ir_frames];
        for(int f=0; f<ir_frames; f++)
        {
            buff_mono[f] = ir_file_data_buff[f * ir_channels + i];
        }
        ir_data.append(buff_mono);
    }
    delete[] ir_file_data_buff;

    // while(ir_data.size() < audio_data.size())
    // {
    //     ir_data.append(ir_data[ir_data.size()-1]);
    // }
    // emit deal_progress(0);
    qInfo() << "开始运算...";
    deal_sample_max = audio_frames * audio_channels + 1;
    deal_sample_count = 0;

    for(int i=0; i<audio_data.size(); i++)
    {
        float *ir_buff;
        if(i < ir_data.size())
        {
            ir_buff = ir_data[i];
        }
        else
        {
            ir_buff = ir_data[ir_data.size()-1];
        }
        buff_mono = new float[audio_frames + ir_frames - 1];
        ::memset(buff_mono,0,(audio_frames + ir_frames - 1) * sizeof(float));
        convolution(audio_data[i],audio_frames,ir_buff,ir_frames,buff_mono);
        result_data.append(buff_mono);
        delete[] audio_data[i];
        audio_data[i] = nullptr;
    }
    audio_frames = audio_frames + ir_frames - 1;
    for (int i = 0; i < ir_data.size(); ++i) {
        if(ir_data[i] != nullptr)
        {
            delete[] ir_data[i];
            ir_data[i] = nullptr;
        }
    }
    qInfo() << "运算完成";
    qInfo() << "开始生成文件";
    SNDFILE *osnd;
    SF_INFO oinfo;
    oinfo.channels = result_data.size();
    oinfo.samplerate = ir_sample_rate;
    oinfo.format = SF_FORMAT_WAV | SF_FORMAT_PCM_24;
    osnd = sf_open("__result_ir.wav",SFM_WRITE,&oinfo);
    if(osnd)
    {
        int of = audio_frames;
        float *mul_ch_buff = new float[of * oinfo.channels];
        float *mono_buff[10];
        for(int c=0; c<result_data.size(); c++)
        {
            mono_buff[c] = result_data[c];
        }
        int m=0;
        for(int i=0; i<of; i++)
        {
            for(int c=0; c<oinfo.channels; c++)
            {
                mul_ch_buff[m++] = *(mono_buff[c] + i);
            }
        }
        int rd = sf_writef_float(osnd,(const float *)mul_ch_buff,of);
        // int rd = sf_write_float(osnd,result_data[0],of);
        qInfo() << "写入帧数:" << rd;
        sf_close(osnd);
        qInfo() << "生成文件成功";
        delete[] mul_ch_buff;
        // emit deal_progress(100);
    }
    else
    {
        qCritical() << "生成文件失败";
    }
    for(int i=0; i<result_data.size(); i++)
    {
        if(result_data[i] != nullptr)
        {
            delete[] result_data[i];
            result_data[i] = nullptr;
        }
    }
    // emit deal_progress(100);
    deal_sample_count = deal_sample_max;
    qDebug() << "退出";
}
